/**
 * Copyright � 2012 GestureSoft. ALL RIGHTS RESERVED.
 * This file contains proprietary and GestureSoft CONFIDENTIAL Information.
 * Use, disclosure or reproduction is prohibited.
 * 
 * @fileName ZipDownloader.as
 * @creationDate Aug 8, 2012
 * @author 
 * @version 1.0
 */
package com.gesturesoft.imultimax.model
{
	
	import com.gesturesoft.imultimax.AppConst;
	import com.gesturesoft.imultimax.events.CustomProgressEvent;
	import com.gesturesoft.imultimax.model.completor.Completor;
	import com.gesturesoft.imultimax.model.interfaces.IZipDownloader;
	import com.gesturesoft.imultimax.model.loader.events.LoadFaultEvent;
	import com.gesturesoft.imultimax.model.vo.AppVO;
	
	import flash.events.Event;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.OutputProgressEvent;
	import flash.events.ProgressEvent;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.net.URLRequest;
	import flash.net.URLStream;
	import flash.utils.ByteArray;
	
	import mx.collections.ArrayCollection;

	public class ZipDownloader extends Completor implements IZipDownloader
	{
		private var _assets4Updation:ArrayCollection;
		private var stream :URLStream;
		private var fileAccess :FileStream;
		private var remotePath :String;
		private var targetPath :String;
		private var localFile :File = null; 
		private var currentPosition :uint = 0;
		private var assetCount:int = 0;
		
		private var netConnected:Boolean = true;
		
		public function ZipDownloader(items4Updation:ArrayCollection)
		{
			
			assets4Updation = items4Updation;
			assetCount = assets4Updation.length;
			
		}
		
		/**
		 * Download all the assets files 
		 * 
		 */ 
		
		public function download():void
		{
			
			assetCount -= 1;
			if( assetCount < 0 )
			{
				
				super.complete(this);
				return;
				
			}
				
			var appVO:AppVO = this._assets4Updation[assetCount];
			
			localFile = File.applicationStorageDirectory.resolvePath(appVO.name+"/assets.zip");
			trace("local file url : "+localFile.url);
			
			remotePath = "http://"+appVO.server+"/"+appVO.configFile;
			trace("remote file url : "+remotePath);
			
			if( !stream || !stream.connected ) 
			{
				
				stream = new URLStream();
				fileAccess = new FileStream();
				fileAccess.addEventListener(IOErrorEvent.IO_ERROR, onWriteError);
				
				var requester :URLRequest = new URLRequest( remotePath );
				fileAccess.open( localFile, FileMode.UPDATE);
				stream.addEventListener(ProgressEvent.PROGRESS,downloadProgress);
				stream.addEventListener(Event.COMPLETE,onCompelte);
				stream.addEventListener(IOErrorEvent.IO_ERROR,onReadError);
				stream.addEventListener(HTTPStatusEvent.HTTP_STATUS,onHTTPStatus);
				stream.load( requester );
				
			}
			
		}
		
		/**
		 * Dispatch event if write to local file system failed
		 */
		
		private function onWriteError():void
		{
			
			dispatchEvent(new LoadFaultEvent(LoadFaultEvent.LOAD_FAILED, "Access denied by local file system"));
			
		}
		
		private function onReadError(event : IOErrorEvent):void
		{
			
			if(netConnected)
			{
				
				trace(event);
				dispatchEvent(new LoadFaultEvent(LoadFaultEvent.LOAD_FAILED, AppConst.CONFIG_FILE_LOAD_FAILED));
				
			}
			
		}
		
		private function onHTTPStatus(event:HTTPStatusEvent):void
		{
			
			if(event.status == 0)
			{
				
				netConnected = false;
				dispatchEvent(new LoadFaultEvent(LoadFaultEvent.LOAD_FAILED, AppConst.NET_CONNECTION_FAILED));
				
			}
				
		}
		
		private  function downloadProgress(event:ProgressEvent):void
		{
			
			var bytes :ByteArray = new ByteArray();
			var thisStart :uint = currentPosition;
			currentPosition += stream.bytesAvailable;
			stream.readBytes( bytes, thisStart );
			fileAccess.writeBytes( bytes, thisStart );
			dispatchEvent(new CustomProgressEvent(CustomProgressEvent.LOAD_PROGRESS,event.bytesLoaded,event.bytesTotal));
			
		}
		
		private  function onCompelte(event:Event):void
		{
			
			if( assetCount >= 0 )
			{
				
				stream.close();
				fileAccess.close();
				fileAccess=null;
				stream=null;
				dispatchEvent(new CustomProgressEvent(CustomProgressEvent.LOAD_COMPLETE));
				download();
				
			}
			else
			{
				
				super.complete(this);
				
			}
			
		}
		
		public function get assets4Updation():ArrayCollection
		{
			
			return _assets4Updation;
			
		}
		
		public function set assets4Updation(val:ArrayCollection):void
		{
			
			_assets4Updation = val;
			
		}
		
	}
	
}